// #define _USE_MATH_DEFINES
#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

#include "util/jni_util.h"
#include "util/log_util.h"

jdouble native_toRadians(JNIEnv *env, jclass clazz, jdouble deg) {
  return deg / 180.0 * M_PI;
}

jdouble native_toDegrees(JNIEnv *env, jclass clazz, jdouble rad) {
  return rad * 180.0 / M_PI;
}

jdouble native_sin(JNIEnv *env, jclass clazz, jdouble rad) {
  return sin(rad);
}

jdouble native_asin(JNIEnv *env, jclass clazz, jdouble rad) {
  return asin(rad);
}

jdouble native_cos(JNIEnv *env, jclass clazz, jdouble rad) {
  return cos(rad);
}

jdouble native_acos(JNIEnv *env, jclass clazz, jdouble rad) {
  return acos(rad);
}

jdouble native_tan(JNIEnv *env, jclass clazz, jdouble rad) {
  return tan(rad);
}

jdouble native_atan(JNIEnv *env, jclass clazz, jdouble rad) {
  return atan(rad);
}

jdouble native_atan2(JNIEnv *env, jclass clazz, jdouble y, jdouble x) {
  return atan2(y, x);
}

// register natives

CJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void */*reserved*/) {
  // LOGI(__func__);
  JNIEnv *env = nullptr;
  if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
    LOGW("JNI_OnLoad GetEnv error");
    return JNI_ERR;
  }

  static JNINativeMethod methods[] = {
    {"toRadians", "(D)D", reinterpret_cast<void*>(native_toRadians)},
    {"toDegrees", "(D)D", reinterpret_cast<void*>(native_toDegrees)},
    {"sin", "(D)D", reinterpret_cast<void*>(native_sin)},
    {"asin", "(D)D", reinterpret_cast<void*>(native_asin)},
    {"cos", "(D)D", reinterpret_cast<void*>(native_cos)},
    {"acos", "(D)D", reinterpret_cast<void*>(native_acos)},
    {"tan", "(D)D", reinterpret_cast<void*>(native_tan)},
    {"atan", "(D)D", reinterpret_cast<void*>(native_atan)},
    {"atan2", "(DD)D", reinterpret_cast<void*>(native_atan2)},
  };
  registerNatives(env, "cc/eevee/jni/libdynamic/Math", methods,
      sizeof(methods) / sizeof(methods[0]));

  return JNI_VERSION_1_6;
}

CJNIEXPORT void JNICALL JNI_OnUnload(JavaVM */*jvm*/, void */*reserved*/) {
  // LOGI(__func__);
}
